package cn.edu.shou.lab.web.api;

import cn.edu.shou.lab.config.constant.SHOU;
import cn.edu.shou.lab.config.converters.BackResult;
import cn.edu.shou.lab.config.query.Retrieval;
import cn.edu.shou.lab.config.query.Term;
import cn.edu.shou.lab.config.utils.FileStreamUtil;
import cn.edu.shou.lab.config.utils.FileUploadUtil;
import cn.edu.shou.lab.config.utils.FormatUtil;
import cn.edu.shou.lab.service.CohesionServiceI;
import org.aspectj.util.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.logging.Logger;

@RestController
@RequestMapping(value = "/api/v1")
public class RestfulApiController {

    private final static Logger LOGGER = Logger.getLogger(RestfulApiController.class.getName());

    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private CohesionServiceI cohesionService;

    /**
     * 删除实体类
     * @param dataTable 数据表名称
     */
    @RequestMapping(value = "/delete/{dataTable}/{id}")
    @Transactional
    public BackResult delete(@PathVariable("dataTable") String dataTable,
                             @PathVariable String id,
                             HttpServletRequest request) {
        Object userInfo = request.getSession().getAttribute("user");
        return cohesionService.executeDelete(dataTable, Arrays.asList(id));

    }

    /**
     * 批量删除实体类
     * @param dataTable 数据表名称
     */
    @RequestMapping(value = "/batchDelete/{dataTable}")
    @Transactional
    public BackResult deleteEntity(@PathVariable("dataTable") String dataTable,
                                   @RequestBody List<String> ids,
                                   HttpServletRequest request) {
        Object userInfo = request.getSession().getAttribute("user");
        return cohesionService.executeDelete(dataTable, ids);
    }


    /**
     * 插入实体类
     *
     * @param dataTable 数据表名称
     */
    @RequestMapping(value = "/save/{dataTable}", method = RequestMethod.POST)
    @Transactional
    public BackResult saveOrUpdateEntity(@PathVariable String dataTable,
                                         @RequestBody Map<String, Object> datas,
                                         HttpServletRequest request) {
        Object userInfo = request.getSession().getAttribute("user");
        return cohesionService.executeSaveOrUpdate(dataTable, Arrays.asList(datas));
    }

    /**
     * 批量插入实体类
     *
     * @param dataTable 数据表名称
     */
    @RequestMapping(value = "/batchSave/{dataTable}")
    @Transactional
    public BackResult batchSaveOrUpdateEntity(@PathVariable String dataTable,
                                              @RequestBody List<Map<String, Object>> datas,
                                              HttpServletRequest request) {
        Object userInfo = request.getSession().getAttribute("user");
        return cohesionService.executeSaveOrUpdate(dataTable, datas);
    }


    /**
     * 查询实体类（多条件、近似、精确、分页 查询单一实体类）
     * @param dataTable 查询表名
     * @param conditions 查询条件
     * @param request 分页大小及当前页（以url形式传递可选参数）
     * @return
     */
    @RequestMapping(value = "/find/{dataTable}", method = RequestMethod.POST)
    @Transactional
    public Map<String, Object> find(@PathVariable String dataTable,
                                    @RequestBody List<Retrieval> conditions,
                                    HttpServletRequest request) {
        String pageSize = request.getParameter("pageSize");
        String pageNum = request.getParameter("pageNum");
        List<Map<String, Object>> list;
        Map<String, Object> results = new HashMap<>();
        Pageable pageable = null;
        if(pageNum!=null && pageSize!=null){
            pageable = PageRequest.of(Integer.parseInt(pageNum),Integer.parseInt(pageSize));
        }
        list = cohesionService.executeQuery(dataTable, conditions, pageable);
        results.put("result", FormatUtil.getLowerCaseFields(list));
        return results;
    }

    /**
     * 查询实体类（多条件、近似、精确、分页 查询 多实体类）
     * @param dataTable 查询表名
     * @param term 查询条件
     * @param request 分页大小及当前页（以url形式传递可选参数）
     * @return BackResult
     */
    @RequestMapping(value = "/seniorFind/{dataTable}", method = RequestMethod.POST)
    @Transactional
    public BackResult seniorFind(@PathVariable String dataTable,
                                 @RequestBody Term term,
                                 HttpServletRequest request) {
        BackResult result = new BackResult();
        Object userInfo = request.getSession().getAttribute("user");
        try {
            if (result.isState()) {
                String pageSize = request.getParameter("pageSize");
                String pageNum = request.getParameter("pageNum");
                List<Map<String, Object>> list;
                Map<String, Object> data = null;
                Pageable pageable = null;
                if (pageNum != null && pageSize != null) {
                    pageable = PageRequest.of(Integer.parseInt(pageNum), Integer.parseInt(pageSize));
                }
                list = cohesionService.executeQuery(dataTable, term, pageable);
                data = cohesionService.getCount(dataTable, term);
                data.put("result", list);
                result.setData(data);
            }
        }catch (Exception e){
            result.setState(false);
            result.setMsg(e.getMessage());
            LOGGER.warning(e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    @RequestMapping(value = "/queryDiff/{dataTable}/{distinctColumn}")
    public List queryDiffEntity(@PathVariable String dataTable,
                                @RequestParam Map<String, Object> checkValue,
                                @PathVariable String distinctColumn) {
        String queryForList = "select distinct (" + distinctColumn + ") from " + dataTable + " where ";
        int initQueryLength = queryForList.length();
        for (Map.Entry<String, Object> entry : checkValue.entrySet()) {
            if (!(entry.getValue() == null || entry.getValue().equals(""))) {
                queryForList += " " + entry.getKey() + " =  '" + entry.getValue() + "' and";
            }
        }
        queryForList = queryForList.substring(0, queryForList.length() - 3) + ";";
        if (initQueryLength + 1 > queryForList.length()) {
            queryForList = queryForList.substring(0, queryForList.length() - 5);
        }
        List<Map<String, Object>> list = jdbcTemplate.queryForList(queryForList);
        List<Object> cache = new ArrayList<>();
        for(Map<String, Object> e: list)
            cache.addAll(e.values());
        return cache;
    }


    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @Transactional
    public BackResult upload(@RequestParam("file") MultipartFile file) {
        BackResult result = new BackResult();
        String fileName = file.getOriginalFilename();  //文件名字
        String path;
        try {
            path = FileUploadUtil.saveFile(file.getInputStream(), fileName, null, SHOU.FILE_PATH, true);
            result.setData(path);
        } catch (Exception e) {
            result.setState(false);
            result.setMsg(e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    @RequestMapping(value = "/download/{fileName}", method = RequestMethod.POST)
    @Transactional
    public void download(@PathVariable String fileName, HttpServletResponse response) {
        InputStream inputStream = null;
        BackResult result = new BackResult();
        try {
            inputStream = FileStreamUtil.getFileStream(SHOU.FILE_PATH + fileName);
            FileUtil.copyStream(inputStream, response.getOutputStream());
        } catch (Exception e) {
            result.setState(false);
            result.setMsg(e.getMessage());
            e.printStackTrace();
        }finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
